package middleware

import (
	"cgs-server/helper"
	"cgs-server/internal/pkg/code"
	"cgs-server/pkg/log"
	"cgs-server/pkg/set"
	"cgs-server/server"
	"context"
	"git.mapchang.com/go/base/core"
	"git.mapchang.com/go/errors"
	"github.com/gin-gonic/gin"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"strings"
)

var urlSet = set.NewSetFormSlice([]interface{}{
	"/api/Cgs/Portal/Visual/Detail",
	"/api/Cgs/Portal/CgsMap/detail",
	"/api/Cgs/Worksheet/GetWorksheetInfo",
	"/api/Cgs/Worksheet/GetWorksheetInfoById",
	"/api/Cgs/Worksheet/GetFilterData",
})

func AccessTokenMiddleware(c *gin.Context) {
	r := c.Request

	//if !urlSet.Contains(r.URL.Path) {
	//	next(w, r)
	//	return
	//}

	auth, ok := server.GetApiAuthority(r.URL.Path)
	if !ok {
		// path is not registered.
		log.Errorf("%v is not registered", r.URL.Path)
		core.WriteResponse(c, errors.WithCode(code.ErrPageNotFound, "访问的路径不存在"), nil)
		c.Abort()
		return
	}

	// api needs no authority
	if auth.Auth == string(server.None) {
		logAPI2(r.URL.Path, auth.Auth, "", true)
		c.Next()
		return
	}

	// api needs no authority
	accessToken := ""
	if len(r.Header) > 0 {
		for k, v := range r.Header {
			if k == "Access-Token" {
				accessToken = v[0]
			}
		}
	}
	if accessToken == "" {
		c.Next()
		return
	}

	db, err := server.Mongo()
	if err != nil {
		core.WriteResponse(c, errors.WithCode(code.ErrDatabase, "数据库连接失败"), nil)
		c.Abort()
		return
	}
	decryptBase62 := helper.DecryptBase62(accessToken)
	split := strings.Split(decryptBase62, "&")
	if len(split) != 3 {
		c.Next()
		return
	}

	appKey := split[0]
	appSecret := split[1]
	timestamp := split[2]

	filter := bson.M{
		"AppKey": appKey,
	}
	doc := AppKey{}
	find, _ := db.FindOne(server.CgsAppKeyCollectionName, filter, &doc)
	if !find {
		c.Next()
		return
	} else {

		if doc.AuthType == "0" {
			// 密钥未启用
			c.Next()
			return
		}

		if appSecret != doc.AppSecret || timestamp != doc.Timestamp {
			c.Next()
			return
		}

		//if len(doc.WhiteList) > 0 {
		//	helper.EnableCrossDomain(w, r, doc.WhiteList...)
		//}

		ctx := context.WithValue(r.Context(), "userID", doc.UserID)
		ctx = context.WithValue(ctx, "authType", doc.AuthType)
		r = r.WithContext(ctx)
		c.Request = r
		c.Next()
		return
	}
}

type AppKey struct {
	ID        primitive.ObjectID
	AppKey    string
	AppSecret string
	Sign      string
	AuthType  string //0 未启用  1//只读  2//读写
	Remark    string
	Timestamp string
	UserID    string
	// WhiteList 访问白名单
	WhiteList []string
}
